
#include <stm32f103.h>

#include <rcc.h>
#include <gpio.h>

#include <usart.h>
#include <string.h>


#define USART1_BASE			(APB2PERIPH_BASE + 0x3800)
#define USART2_BASE			(APB1PERIPH_BASE + 0x4400)
#define USART3_BASE			(APB1PERIPH_BASE + 0x4800)
 
typedef struct
{
	__IO uint16_t SR;
	uint16_t  RESERVED0;
	__IO uint16_t DR;
	uint16_t  RESERVED1;
	__IO uint16_t BRR;
	uint16_t  RESERVED2;
	__IO uint16_t CR1;
	uint16_t  RESERVED3;
	__IO uint16_t CR2;
	uint16_t  RESERVED4;
	__IO uint16_t CR3;
	uint16_t  RESERVED5;
	__IO uint16_t GTPR;
	uint16_t  RESERVED6;
} USART_TypeDef;

/*static void usart1_send_char(unsigned char a)
{
	USART_SendData(USART1, (unsigned char)a);
	while (!(USART1->SR & USART_FLAG_TXE));
}

static void usart1_send_string(unsigned char *str)
{
	if(NULL != str)
	{
		while(*str)
		{
			usart1_send_char(*str++);
		}
	}
}

static void usart1_send_int(int val, int mode)
{
	unsigned char buffer[32] = {0};
	usart1_send_string(itoa_r(val, mode, buffer, sizeof(buffer)));
}

static void usart_send_array(void *array, int num, int type, int mode)
{
	int i = 0;
	switch(type)
	{
		case 1:
			for(i = 0; i < num; i++)
			{
				usart1_send_int(((unsigned char *)array)[i], mode);
				if(i != num - 1)
				{
					usart1_send_string(", ");
				}
			}
			break;
		case 2:
			for(i = 0; i < num; i++)
			{
				usart1_send_int(((unsigned short *)array)[i], mode);
				if(i != num - 1)
				{
					usart1_send_string(", ");
				}
			}
			break;
		case 4:
			for(i = 0; i < num; i++)
			{
				usart1_send_int(((unsigned int *)array)[i], mode);
				if(i != num - 1)
				{
					usart1_send_string(", ");
				}
			}
			break;
		default:
			//usart1_send_string("bad type!!!\r\n");
			break;
	}
}

static void usart1_send_crlf(int num)
{
	for(int i = 0; i < num; i++)
	{
		usart1_send_char(0xA);
		usart1_send_char(0xD);
	}
}

static void usart1_send_mem(unsigned char *data, unsigned int len)
{
	int i = 0;
	usart1_send_crlf(1);
	for(i = 0; i < len; i++)
	{
		if(0 == i % 16)
		{
			usart1_send_char(i / 16 + '0');
			usart1_send_char(':');
			usart1_send_char(0x20);
		}
		if(0xF >= data[i])
		{
			usart1_send_char('0');
		}
		usart1_send_int(data[i], 2);
		if(0 == (i + 1) % 16)
		{
			usart1_send_char(0xA);
			usart1_send_char(0xD);
		}
		else if(0 == (i + 1) % 8)
		{
			usart1_send_char(0x9);
		}
		else
		{
			usart1_send_char(0x20);
		}
	}
	usart1_send_crlf(2);
}*/

static void usart1_gpio_init(void)
{
	rcc_enable(RCC_APB2, RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA);
	gpio_mode(GPIO_A, GPIO_PIN_9, GPIO_MODE_AF_PP | GPIO_SPEED_50MHZ);
	gpio_mode(GPIO_A, GPIO_PIN_10, GPIO_MODE_IN_FLOATING);
}


static void usart_usart_init(USART_TypeDef *USARTx)
{
	USARTx->CR1 |= (uint16_t)0xDFFF;
	/*USART_InitStructure.USART_BaudRate = 115200;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	USART_Init(USART1, &USART_InitStructure);*/
	USARTx->CR1 |= (uint16_t)0x2000;
	
}

static USART_TypeDef *USARTx[] = {(USART_TypeDef *)USART1_BASE, (USART_TypeDef *)USART2_BASE, (USART_TypeDef *)USART3_BASE};

/*
static USART1_INTERFACE_T _obj_usart1 = {
	.send_char = usart1_send_char,
	.send_string = usart1_send_string,
	.send_int = usart1_send_int,
	.send_array = usart_send_array,
	.send_crlf = usart1_send_crlf,
	.send_mem = usart1_send_mem
};
*/
void usart1_init(unsigned int usart)
{
	usart1_gpio_init();
	usart_usart_init(USARTx[usart]);
	//usart1_send_string("\r\n\r\n\r\n\r\n\r\n\r\nUSART1 is ready!!!\r\n");
}

void usart1_get_interface(USART1_INTERFACE_P *obj)
{
	//*obj = &_obj_usart1;
}
